<?php

/**
 * @author 暮雨秋晨
 * @copyright 2014
 */

class TemplateCompile
{
    private static $l_d = '{'; //左
    private static $r_d = '}'; //右
    private static $dir; //模板路径
    private static $tpl = 'default'; //模板名
    private $literal = array();

    public function __construct($l, $r, $d, $t)
    {
        self::$l_d = $l;
        self::$r_d = $r;
        self::$dir = $d;
        self::$tpl = $t;
        return true;
    }

    public function compile($res)
    {
        return $this->parse_Tpl($res);
    }

    /**
     * 编译模板
     */
    private function parse_Tpl($res)
    {
        $dir = self::$dir;
        $res = preg_replace_callback('!' . self::$l_d . 'include\s+[\'|"](.*)[\'|"]' .
            self::$r_d . '!Uis', function ($file)use ($dir)
        {
            return file_get_contents($dir . $file[1]); }
        , $res);

        $res = $this->parse_literal($res);
        $res = $this->parse_notes($res);
        $res = $this->parse_constant($res);
        $res = $this->parse_variable($res);
        $res = $this->parse_for($res);
        $res = $this->parse_foreach($res);
        $res = $this->parse_if($res);
        $res = $this->parse_switch($res);
        $res = $this->parse_array($res);
        //还原literal
        if (!empty($this->literal)) {
            foreach ($this->literal as $key => $val) {
                $res = str_replace('{' . $key . '}', nl2br(htmlspecialchars($val)), $res);
            }
        }
        $res = "<?php defined('ROOT_DIR') or die('Access denied!');?>\r\n" . $res;
        return $res;
    }

    private function parse_array($res)
    {
        $regex = array('!' . self::$l_d . '\$(.*)\[(\d)\]' . self::$r_d . '!Uis', );
        $source = array('<?php echo $$1[$2];?>', );
        $res = preg_replace($regex, $source, $res);
        return $res;
    }

    private function parse_literal($res)
    {
        if (preg_match_all('!' . self::$l_d . 'literal' . self::$r_d . '(.*)' . self::$l_d .
            '\/literal' . self::$r_d . '!Uis', $res, $match)) {
            foreach ($match[1] as $key => $val) {
                $uniqid_literal = uniqid('literal_' . rand(10, 99));
                $res = str_replace($match[0][$key], '{' . $uniqid_literal . '}', $res);
                $this->literal[$uniqid_literal] = $val;
            }
        }
        return $res;
    }

    private function parse_constant($res)
    {
        $res = str_replace(self::$l_d . '__STATIC__' . self::$r_d, '/' . APP . '/' . STC,
            $res);
        return $res;
    }

    private function parse_notes($res)
    {
        $res = preg_replace('!' . self::$l_d . '\#(.*)\#' . self::$r_d . '!Uis',
            '<!--{ $1 }>--!>', $res);
        return $res;
    }

    private function parse_variable($res)
    {
        $regex = array(
            '!' . self::$l_d . '\$(.*)' . self::$r_d . '!Uis',
            '!' . self::$l_d . '\:(.*)' . self::$r_d . '!Uis',
            '!' . self::$l_d . 'F:(.*)' . self::$r_d . '!Uis');
        $source = array(
            '<?php echo \$$1;?>',
            '$1',
            '<?php echo $1;?>');
        $res = preg_replace($regex, $source, $res);
        return $res;
    }

    private function parse_switch($res)
    {
        $regex = array(
            '!' . self::$l_d . 'switch\((.*)\)' . self::$r_d . '!Uis',
            '!' . self::$l_d . '\/switch' . self::$r_d . '!Uis',
            '!' . self::$l_d . 'case\s+(.*)' . self::$r_d . '!Uis',
            '!' . self::$l_d . '\/case' . self::$r_d . '!Uis',
            '!' . self::$l_d . 'default' . self::$r_d . '!Uis');
        $source = array(
            '<?php switch($1):?>',
            '<?php endswitch;?>',
            '<?php case $1:?>',
            '<?php break;?>',
            '<?php default:?>');
        $res = preg_replace($regex, $source, $res);
        return $res;
    }

    private function parse_for($res)
    {
        $regex = array('!' . self::$l_d . 'for\((.*);(.*);(.*)\)' . self::$r_d . '!Uis',
                '!' . self::$l_d . '\/for' . self::$r_d . '!Uis');
        $source = array('<?php for($1;$2;$3):?>', '<?php endfor;?>');
        $res = preg_replace($regex, $source, $res);
        return $res;
    }

    private function parse_foreach($res)
    {
        $regex = array(
            '!' . self::$l_d . 'foreach\s+(.*)\s+as\s+(.*)' . self::$r_d . '!Uis',
            '!' . self::$l_d . 'foreach\s+(.*)\s+as\s+(.*)\=\>(.*)' . self::$r_d . '!Uis',
            '!' . self::$l_d . '\/foreach' . self::$r_d . '!Uis');
        $source = array(
            '<?php foreach($1 as $2):?>',
            '<?php foreach($1 as $2=>$3):?>',
            '<?php endforeach;?>');
        $res = preg_replace($regex, $source, $res);
        return $res;
    }

    private function parse_if($res)
    {
        $regex = array(
            '!' . self::$l_d . 'if\((.*)\)' . self::$r_d . '!Uis',
            '!' . self::$l_d . 'elseif\((.*)\)' . self::$r_d . '!Uis',
            '!' . self::$l_d . 'else' . self::$r_d . '!Uis',
            '!' . self::$l_d . '\/if' . self::$r_d . '!Uis');
        $source = array(
            '<?php if($1):?>',
            '<?php elseif($1):?>',
            '<?php else:?>',
            '<?php endif;?>');
        $res = preg_replace($regex, $source, $res);
        return $res;
    }
}

?>